// -*- c-basic-offset: 2 default-tab-width: 2 indent-tabs-mode: t -*-
// vim: autoindent tabstop=2 noexpandtab shiftwidth=2 softtabstop=2
#define CALL(__type, __method, ...)\
	CALL_##__type(__method, __VA_ARGS__)
#define DEFINE_METHOD(__method, ...)\
	DEFINE_METHOD_CAT_TOKENS(DEFINE_METHOD_, __VA_ARGS__) (__method, __VA_ARGS__)
#define EXPORT_METHOD(__method, ...)\
	DEFINE_METHOD_CAT_TOKENS(EXPORT_METHOD_, __VA_ARGS__) (__method, __VA_ARGS__)

#define DEFINE_METHOD_MAKE_SIG(__return_type, ...)\
	(__return_type (*) (Star##__VA_ARGS__))
#define DEFINE_METHOD_MAKE_DECL(__method, __return_type, ...)\
	__return_type (*__method[]) (Star##__VA_ARGS__)
#define DEFINE_METHOD_CAT_TOKENS(__token, __ret, __type, ...)\
	__token##__type

#define SXP_LOW_PART	3
#define CALL_METHOD_RELAY_CALL(__x, ...)\
	(__x ? (TYPE(__x) >> SXP_LOW_PART) : 0)
#define Any_ID		248
#define Any_MASK	0
#define IS_Any(__x)\
	(!((__x & Any_MASK) ^ (Any_ID & Any_MASK)))
#define StarAny Any*
#define DEFINE_METHOD_Any(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Null,\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Symbol, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Promise, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_EPtr, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_WRef, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_List, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_S4, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Closure, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Builtin, \
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Special, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Raw, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Environment, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Logical, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Int, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Double, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Complex, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_String, \
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Vector, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Expression\
	}
#define CALL_Any(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Any(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define Atom_ID		248
#define Atom_MASK	1
#define IS_Atom(__x)\
	(!((__x & Atom_MASK) ^ (Atom_ID & Atom_MASK)))
#define StarAtom Atom*
#define DEFINE_METHOD_Atom(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Symbol, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Promise, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_EPtr, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_WRef, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_List, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_S4, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Closure, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Builtin, \
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Special\
	}
#define CALL_Atom(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Atom(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define Symbol_ID	14
#define Symbol_MASK	255
#define IS_Symbol(__x)\
	(!((__x & Symbol_MASK) ^ (Symbol_ID & Symbol_MASK)))
#define StarSymbol Symbol*
#define CALL_Symbol(__method, ...)\
	__method##_Symbol](__VA_ARGS__)
#define Promise_ID	22
#define Promise_MASK	255
#define IS_Promise(__x)\
	(!((__x & Promise_MASK) ^ (Promise_ID & Promise_MASK)))
#define StarPromise Promise*
#define CALL_Promise(__method, ...)\
	__method##_Promise](__VA_ARGS__)
#define Ref_ID		248
#define Ref_MASK	7
#define IS_Ref(__x)\
	(!((__x & Ref_MASK) ^ (Ref_ID & Ref_MASK)))
#define StarRef Ref*
#define DEFINE_METHOD_Ref(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_EPtr, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_WRef\
	}
#define CALL_Ref(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Ref(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define EPtr_ID		24
#define EPtr_MASK	255
#define IS_EPtr(__x)\
	(!((__x & EPtr_MASK) ^ (EPtr_ID & EPtr_MASK)))
#define StarEPtr EPtr*
#define CALL_EPtr(__method, ...)\
	__method##_EPtr](__VA_ARGS__)
#define WRef_ID		32
#define WRef_MASK	255
#define IS_WRef(__x)\
	(!((__x & WRef_MASK) ^ (WRef_ID & WRef_MASK)))
#define StarWRef WRef*
#define CALL_WRef(__method, ...)\
	__method##_WRef](__VA_ARGS__)
#define Cons_ID		250
#define Cons_MASK	7
#define IS_Cons(__x)\
	(!((__x & Cons_MASK) ^ (Cons_ID & Cons_MASK)))
#define StarCons Cons*
#define DEFINE_METHOD_Cons(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_List, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_S4\
	}
#define CALL_Cons(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Cons(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define List_ID		42
#define List_MASK	255
#define IS_List(__x)\
	(!((__x & List_MASK) ^ (List_ID & List_MASK)))
#define StarList List*
#define CALL_List(__method, ...)\
	__method##_List](__VA_ARGS__)
#define S4_ID		50
#define S4_MASK	255
#define IS_S4(__x)\
	(!((__x & S4_MASK) ^ (S4_ID & S4_MASK)))
#define StarS4 S4*
#define CALL_S4(__method, ...)\
	__method##_S4](__VA_ARGS__)
#define Lambda_ID	252
#define Lambda_MASK	7
#define IS_Lambda(__x)\
	(!((__x & Lambda_MASK) ^ (Lambda_ID & Lambda_MASK)))
#define StarLambda Lambda*
#define DEFINE_METHOD_Lambda(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Closure, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Builtin, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Special\
	}
#define CALL_Lambda(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Lambda(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define Closure_ID	60
#define Closure_MASK	255
#define IS_Closure(__x)\
	(!((__x & Closure_MASK) ^ (Closure_ID & Closure_MASK)))
#define StarClosure Closure*
#define CALL_Closure(__method, ...)\
	__method##_Closure](__VA_ARGS__)
#define Builtin_ID	68
#define Builtin_MASK	255
#define IS_Builtin(__x)\
	(!((__x & Builtin_MASK) ^ (Builtin_ID & Builtin_MASK)))
#define StarBuiltin Builtin*
#define CALL_Builtin(__method, ...)\
	__method##_Builtin](__VA_ARGS__)
#define Special_ID	76
#define Special_MASK	255
#define IS_Special(__x)\
	(!((__x & Special_MASK) ^ (Special_ID & Special_MASK)))
#define StarSpecial Special*
#define CALL_Special(__method, ...)\
	__method##_Special](__VA_ARGS__)
#define Array_ID	249
#define Array_MASK	1
#define IS_Array(__x)\
	(!((__x & Array_MASK) ^ (Array_ID & Array_MASK)))
#define StarArray Array*
#define DEFINE_METHOD_Array(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Raw, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Environment, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Logical, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Int, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Double, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Complex, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_String, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Vector, \
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Expression\
	}
#define CALL_Array(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Array(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define Raw_ID		87
#define Raw_MASK	255
#define IS_Raw(__x)\
	(!((__x & Raw_MASK) ^ (Raw_ID & Raw_MASK)))
#define StarRaw Raw*
#define CALL_Raw(__method, ...)\
	__method##_Raw](__VA_ARGS__)
#define Environment_ID	95
#define Environment_MASK	255
#define IS_Environment(__x)\
	(!((__x & Environment_MASK) ^ (Environment_ID & Environment_MASK)))
#define StarEnvironment Environment*
#define CALL_Environment(__method, ...)\
	__method##_Environment](__VA_ARGS__)
#define Logical_ID	103
#define Logical_MASK	255
#define IS_Logical(__x)\
	(!((__x & Logical_MASK) ^ (Logical_ID & Logical_MASK)))
#define StarLogical Logical*
#define CALL_Logical(__method, ...)\
	__method##_Logical](__VA_ARGS__)
#define Number_ID	249
#define Number_MASK	3
#define IS_Number(__x)\
	(!((__x & Number_MASK) ^ (Number_ID & Number_MASK)))
#define StarNumber Number*
#define DEFINE_METHOD_Number(__method, ...)\
	DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__) = {\
		DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Int, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Double, DEFINE_METHOD_MAKE_SIG(__VA_ARGS__) __method##_Complex\
	}
#define CALL_Number(__method, ...)\
	__method[CALL_METHOD_RELAY_CALL(__VA_ARGS__,)](__VA_ARGS__)
#define EXPORT_METHOD_Number(__method, ...)\
	extern DEFINE_METHOD_MAKE_DECL(__method, __VA_ARGS__)
#define Int_ID		109
#define Int_MASK	255
#define IS_Int(__x)\
	(!((__x & Int_MASK) ^ (Int_ID & Int_MASK)))
#define StarInt Int*
#define CALL_Int(__method, ...)\
	__method##_Int](__VA_ARGS__)
#define Double_ID	117
#define Double_MASK	255
#define IS_Double(__x)\
	(!((__x & Double_MASK) ^ (Double_ID & Double_MASK)))
#define StarDouble Double*
#define CALL_Double(__method, ...)\
	__method##_Double](__VA_ARGS__)
#define Complex_ID	125
#define Complex_MASK	255
#define IS_Complex(__x)\
	(!((__x & Complex_MASK) ^ (Complex_ID & Complex_MASK)))
#define StarComplex Complex*
#define CALL_Complex(__method, ...)\
	__method##_Complex](__VA_ARGS__)
#define String_ID	135
#define String_MASK	255
#define IS_String(__x)\
	(!((__x & String_MASK) ^ (String_ID & String_MASK)))
#define StarString String*
#define CALL_String(__method, ...)\
	__method##_String](__VA_ARGS__)
#define Vector_ID	143
#define Vector_MASK	255
#define IS_Vector(__x)\
	(!((__x & Vector_MASK) ^ (Vector_ID & Vector_MASK)))
#define StarVector Vector*
#define CALL_Vector(__method, ...)\
	__method##_Vector](__VA_ARGS__)
#define Expression_ID	151
#define Expression_MASK	255
#define IS_Expression(__x)\
	(!((__x & Expression_MASK) ^ (Expression_ID & Expression_MASK)))
#define StarExpression Expression*
#define CALL_Expression(__method, ...)\
	__method##_Expression](__VA_ARGS__)
